use ggez::{Context, graphics, mint::Point2, glam::Vec2};

use crate::physics::Physics;
use crate::visual::Visual;
use crate::animation::Animation;
use crate::animover::Animover;

pub struct Attractor {
    physics : Physics,
    visual: Visual,
}

impl Attractor {
    pub fn new(location: Vec2) -> Attractor {
        let velocity = Vec2{x: 0.0, y: 0.0};
        let acceleration = Vec2 { x: 0.0, y: 0.0 };
        let factor = 30.0;
        let topspeed = 70.0;
        let mass = factor*factor*factor*0.001;
        let physics = Physics{location, velocity, topspeed, acceleration, mass};
        let color = graphics::Color::new(0.0, 0.0, 0.0, 0.8);
        let size = factor;
        let visual = Visual{color, size};
        Attractor {physics, visual}
    }

    pub fn attract(& self, m: &Box<dyn Animover>) -> Vec2 {
        let dirvector = self.physics.location - m.get_location();
        let mut distance = dirvector.length();
        distance = distance.clamp(5.0, 25.0);
        let g = 10.0;
        dirvector.normalize()* (g*self.physics.mass*m.get_mass())/(distance*distance)
    }
}

impl Animation for Attractor {
    fn update(&mut self, ctx: &mut Context) -> () {
        self.physics.location = Vec2{ x: ctx.mouse.position().x, y: ctx.mouse.position().y};
    }

    fn display(&self, ctx: &mut Context, canvas : &mut graphics::Canvas) -> () {
        let circle = graphics::Mesh::new_circle(
            ctx,
            graphics::DrawMode::fill(),
            Point2{x: self.physics.location.x, y: self.physics.location.y},
            self.visual.size,
            0.1,
            self.visual.color,
        ).unwrap();
        canvas.draw(&circle, graphics::DrawParam::default());
        let circle = graphics::Mesh::new_circle(
            ctx,
            graphics::DrawMode::stroke(4.0),
            Point2{x: self.physics.location.x, y: self.physics.location.y},
            self.visual.size,
            0.1,
            graphics::Color::BLACK,
        ).unwrap();
        canvas.draw(&circle, graphics::DrawParam::default());
    }
}